package sf.database.dialect.h2;

import com.querydsl.sql.H2Templates;
import com.querydsl.sql.SQLTemplates;
import org.jooq.SQLDialect;
import sf.database.dialect.DBDialect;
import sf.database.dialect.DBProperty;
import sf.database.dialect.DatabaseDriver;
import sf.database.dialect.Keywords;
import sf.database.meta.ColumnMapping;
import sf.database.meta.TableMapping;
import sf.database.support.RDBMS;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class H2Dialect extends DBDialect {
    @Override
    public DatabaseDriver getDatabaseDriver() {
        return DatabaseDriver.H2;
    }

    @Override
    public RDBMS getName() {
        return RDBMS.h2;
    }

    public H2Dialect() {
        this.keywords.addAll(Keywords.H2);
        setProperty(DBProperty.WRAP_FOR_KEYWORD, "\"\"");
        setProperty(DBProperty.NVL_FUNCTION,"ifnull(%1$s,%2$s)");
    }

    @Override
    public String getDefaultSchema() {
        return "PUBLIC";
    }

    @Override
    public String sqlTableDrop(String table) {
        return String.format("drop table if exists %s;", wrapKeyword(table));
    }

    @Override
    public String sqlTableRename(String oldName, String newName) {
        return String.format("alter table  %s rename to %s;", wrapKeyword(oldName), wrapKeyword(newName));
    }

    @Override
    public String sqlColumnAdd(String table, String column_definition, String column_position) {
        String sql = String.format("alter table %s add column %s", wrapKeyword(table), column_definition);
        if (supportsColumnPosition() && column_position != null) {
            sql = sql + " " + column_position;
        }
        return sql;
    }

    @Override
    public String sqlColumnModify(String table, String column_definition, String column_position) {
        String sql = String.format("alter table %s alter column %s", wrapKeyword(table), column_definition);
        if (supportsColumnPosition() && column_position != null) {
            sql = sql + " " + column_position;
        }
        return sql;
    }

    @Override
    public String sqlColumnDrop(String table, String column) {
        return String.format("alter table %s drop column %s;", wrapKeyword(table), wrapKeyword(column));
    }

    @Override
    public String sqlPageList(String sql, long offset, int limit) {
        sql = sql + " limit " + limit;
        if (offset > 0) {
            sql = sql + " offset " + offset;
        }
        return sql;
    }

    @Override
    public boolean supportsColumnPosition() {
        return true;
    }

    @Override
    public String getHibernateDialect() {
        return "org.hibernate.dialect.H2Dialect";
    }

    @Override
    public String evalFieldType(ColumnMapping mf) {
        return null;
    }

    @Override
    public String uniqueSql(String tableName, String name, String[] columnNames) {
        return null;
    }

    @Override
    public boolean createEntity(Connection conn, TableMapping en) {
        return false;
    }

    public List<String> getIndexNames(TableMapping en, Connection conn) throws SQLException {
        List<String> names = new ArrayList<String>();
        String showIndexs = "SELECT * FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME = ?";
        PreparedStatement preparedStatement = conn.prepareStatement(showIndexs);
        preparedStatement.setString(1, en.getTableName().toUpperCase());
        ResultSet rest = preparedStatement.executeQuery();
        while (rest.next()) {
            String index = rest.getString(5);
            names.add(index);
        }
        return names;
    }

    private static SQLTemplates sqlTemplates = H2Templates.DEFAULT;

    @Override
    public SQLTemplates getQueryDslDialect() {
        return sqlTemplates;
    }

    @Override
    public SQLDialect getJooqDialect() {
        return SQLDialect.H2;
    }
}
